package com.gome.ocean.common.utils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.ChannelExec;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * shell 工具
 * 
 * @author haqiaolong 2016年3月30日 上午11:57:02
 * @since 5.0.0
 */
public class ShellBuilder {

    private static final Logger logger       = LoggerFactory.getLogger(ShellBuilder.class);
    private static final int    DEFAULT_PORT = 22;
    private int                 port;                                                      // 端口
    private String              user;                                                      // 用户
    private String              host;                                                      // IP
    private String              passwd;                                                    // 密码
    private Session             session;
    private File                srcFile;                                                   // 本地文件
    private String              src;
    private String              dst;                                                       // 目标地址
    private String              fileName;                                                  // 文件名
    private int                 mode;                                                      // 传输模式

    protected ShellBuilder(){
    }

    public static ShellBuilder newSehll() {
        return new ShellBuilder();
    }

    public ShellBuilder build() throws JSchException {
        JSch jsch = new JSch();
        session = jsch.getSession(user, host, port == 0 ? DEFAULT_PORT : port);
        session.setPassword(passwd);

        java.util.Properties config = new java.util.Properties();
        config.put("StrictHostKeyChecking", "no");
        session.setConfig(config);
        session.connect();
        return this;
    }

    public ShellBuilder withMode(int mode) {
        this.mode = mode;
        return this;
    }

    public ShellBuilder withFileName(String fileName) {
        this.fileName = fileName;
        return this;
    }

    public ShellBuilder withSrcFile(File srcFile) {
        this.srcFile = srcFile;
        return this;
    }

    public ShellBuilder withDst(String dst) {
        this.dst = dst;
        return this;
    }

    public ShellBuilder withUser(String user) {
        this.user = user;
        return this;
    }

    public ShellBuilder withHost(String host) {
        this.host = host;
        return this;
    }

    public ShellBuilder withPasswd(String passwd) {
        this.passwd = passwd;
        return this;
    }

    public ShellBuilder withPort(int port) {
        this.port = port;
        return this;
    }

    public ShellBuilder withSrc(String src) {
        this.src = src;
        return this;
    }

    public boolean uploadContent() throws JSchException {
        if (StringUtils.isEmpty(fileName)) {
            throw new JSchException("fileName is not empty!");
        }
        if (srcFile == null && StringUtils.isEmpty(src)) {
            throw new JSchException("srcFile or src there must be a !");
        }
        ChannelSftp channel = null;
        InputStream input = null;
        try {
            channel = (ChannelSftp) session.openChannel("sftp");
            channel.connect();
            channel.cd(dst);
            input = new BufferedInputStream(new ByteArrayInputStream(src.getBytes("UTF-8")));
            channel.put(input, fileName, mode);
            channel.quit();
            return Boolean.TRUE;
        } catch (IOException  e) {
            logger.error("远程连接失败!", e);
            return Boolean.FALSE;
        }catch(SftpException e){
        	logger.error("远程连接失败!", e);
            return Boolean.FALSE;
        }catch(JSchException e){
        	logger.error("远程连接失败!", e);
            return Boolean.FALSE;
        }
        finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                }
            }
            channel.disconnect();
            session.disconnect();
        }
    }

    public boolean uploadFile() throws JSchException {
        if (StringUtils.isEmpty(fileName)) {
            throw new JSchException("fileName is not empty!");
        }
        if (srcFile == null && StringUtils.isEmpty(src)) {
            throw new JSchException("srcFile or src there must be a !");
        }
        ChannelSftp channel = null;
        InputStream input = null;
        try {
            channel = (ChannelSftp) session.openChannel("sftp");
            channel.connect();
            input = new BufferedInputStream(new FileInputStream(srcFile));
            channel.cd(dst);
            channel.put(input, fileName, mode);
            channel.quit();
            return Boolean.TRUE;
        } catch (IOException  e) {
            logger.error("远程连接失败!", e);
            return Boolean.FALSE;
        }catch(SftpException e){
        	logger.error("远程连接失败!", e);
            return Boolean.FALSE;
        }catch(JSchException e){
        	logger.error("远程连接失败!", e);
            return Boolean.FALSE;
        } finally {
            if (input != null) {
                try {
                    input.close();
                } catch (IOException e) {
                }
            }
            channel.disconnect();
            session.disconnect();
        }
    }

    /**
     * 执行相关的命令
     * 
     * @throws JSchException
     */
    public String execCmd(String command) throws JSchException {
        BufferedReader reader = null;
        ChannelExec channel = null;

        try {
            while (command != null) {
                channel = (ChannelExec) session.openChannel("exec");
                channel.setPty(true);
                channel.setCommand(command);

                channel.setInputStream(null);
                channel.setErrStream(System.err);

                channel.connect();
                InputStream in = channel.getInputStream();
                reader = new BufferedReader(new InputStreamReader(in));
                String buf = null;
                StringBuffer result = new StringBuffer();
                while ((buf = reader.readLine()) != null) {
                    result.append(buf);
                }
                return result.toString();
            }
            if (logger.isDebugEnabled()) {
                logger.debug("execute command complete! command=" + command);
            }
            return StringUtils.EMPTY;
        } catch (IOException e) {
            logger.error("远程连接失败!", e);
            return StringUtils.EMPTY;
        } catch (JSchException e) {
            logger.error("远程连接失败!", e);
            return StringUtils.EMPTY;
        } finally {
            try {
                reader.close();
            } catch (IOException e) {
            }
            channel.disconnect();
            session.disconnect();
        }
    }

}
